/**
* @file timer_manager.h
* @brief 时间管理
*/
#ifndef TIANYU_COMMON_TIME_MODULE_H_
#define TIANYU_COMMON_TIME_MODULE_H_

#include <stdint.h>
#include <time.h>
#include "common_singleton.h"
#include "timer.h"

namespace common
{

#define GRANULARITY_BITS ( 3 )//粒度，是2的指数倍;
#define WHEEL_BITS ( 8 )
#define WHEEL_SIZE ( 1 << WHEEL_BITS )
#define WHEEL_MASH ( WHEEL_SIZE - 1 )
#define	WHEEL_NUM ( 5 ) 

	/**
	* @brief 时间轮
	*/
	struct STimeWheel
	{
		STimeWheel( );
		~STimeWheel( );
		CListLink< ITimer > spokes[ WHEEL_SIZE ];
		uint32_t spoke_index;
	};

	/**
	* @brief timer管理器
	*/
	class CTimeModule : public ::common::CSingleton<CTimeModule>
	{
	public:

		/**
		* @brief 构造函数
		*/
		CTimeModule( );

		/**
		* @brief 析构函数
		*/
		~CTimeModule( );

		int64_t cur_ms( ) const { return cur_ms_; }

		time_t cur_sec( ) const { return cur_sec_; }

        time_t real_sec( ) const { return cur_sec_ - time_offset_ / 1000; }

		int32_t cur_frame( ) const { return cur_frame_; }

		int32_t week_day() const;

		tm* cur_tm( ) const { return localtime( &cur_sec_ ); }

		int64_t delta_time( ) const { return delta_time_; }

		int32_t cur_day();

		int32_t cur_hms();

		int32_t cur_fullday();

		uint32_t GetDeadlineTime(uint32_t min);

		bool IsSameDayOfMonth(uint32_t day);
		bool IsSameDayOfWeek(uint32_t day);

		int32_t Initialize( int64_t cur_ms );

		int32_t Finalize( );
		/**
		* @brief tick到了
		*/
		void TickUpdate( int64_t cur_ms );

		/**
		* @brief 添加timer
		*
		* @param timer timer
		*
		* @return 添加结果
		*/
		int32_t RegisterTimer( ITimer& timer );


		int32_t UnregisterTimer( ITimer& timer );

		/**
		* @brief 将时间重置到ms
		*
		* @param ms 时间，单位毫秒
		*
		* @return 
		*/
		int32_t ResetTime( int64_t ms );

	private:
		void Cascade( uint32_t index );

		STimeWheel	wheels_[ WHEEL_NUM ];

		int64_t cur_ms_;
		time_t cur_sec_;
		int32_t cur_frame_;
		int64_t delta_time_;
		int64_t time_offset_;
		int32_t time_deviation_;
	};

}

#define CUR_MS	( ::common::CTimeModule::GetInstance( ).cur_ms( ) )
#define CUR_SEC	( ::common::CTimeModule::GetInstance( ).cur_sec( ) )
#define CUR_FRAME ( ::common::CTimeModule::GetInstance( ).cur_frame( ) )
#define TICK_DELTA ( ::common::CTimeModule::GetInstance( ).delta_time( ) )
#define WEEK_DAY ( ::common::CTimeModule::GetInstance( ).week_day( ) )
#define REAL_SEC ( ::common::CTimeModule::GetInstance( ).real_sec( ) )
#define CUR_DAY ( ::common::CTimeModule::GetInstance( ).cur_day( ) )
#define CUR_FULLDAY ( ::common::CTimeModule::GetInstance( ).cur_fullday( ) )
#define CUR_HMS ( ::common::CTimeModule::GetInstance( ).cur_hms( ) )

#endif

